# FILE: WebDocumentManager.py
# DESC: This class manages a collection of WebDocument objects


import MySQLdb

# TODO: move to oreus.conf
MAX_NUM_IMAGES = 5


MAX_NAME_LEN = 256



from infra.logging import logger
from infra.db import DBManager
from infra.exception import * 
from web.factory import EntityFactoryManager
from web.entity.NoneEntity import NoneEntity

class WebDocumentManager:

	def __init__(self, customer):
		self.customer_ = customer
		self.webDocs_ = {}
		isInvariant = False	
		log = logger.getLogger()

		try:
			cursor = DBManager.getCursor()
			log.debug("Fetching WebDocument records of customer = %s from database..." % customer.dump())
			cursor.execute("SELECT * FROM webdocument WHERE customer_id = %s", (self.customer_.getId()))
			webDocRecs = cursor.fetchall()
			log.debug("Fetched %d records." % len(webDocRecs))

			if not webDocRecs:
				webDocRecs = [[-1, self.customer_.getId(), "/", self.customer_.toString(), [], None, None, None, None, -1]]
					
			for webDocRec in webDocRecs: 
				try:
					entityFactory = EntityFactoryManager.findFactory("WebDocument")
					log.debug("Creating WebDocument object from the record = %s ...", webDocRec)
					webDoc = entityFactory.createEntity(self.toWebDocArgs(webDocRec))
					self.webDocs_[webDoc.getRelativeUrl()] = webDoc
					log.debug("Added webDocument = %s to WebDocument dictionary." % webDoc.dump())
				except EntityFactoryManager.NoSuchEntityFactory, e:
					log.error("caught exception NoSuchEntityFactory, reason: %s" % e)
					isInvariant = True
					break
				except InvalidData.InvalidData, e:
					log.error("caught exception InvalidData, reason: %s" % e)
					isInvariant = True
					break

			cursor.close()

		except MySQLdb.Error, e:
			log.error("MySQLdb error %d: %s" % (e.args[0], e.args[1]))
			isInvariant = True

		if isInvariant:
			raise InvariantError.InvariantError("%s not initialized!" % self)


	def toWebDocArgs(self, webDocRec):
		webDocArgs = []
		log = logger.getLogger()

		try:
			webDocArgs.append(webDocRec[0])

			webDocArgs.append(webDocRec[1])

			# absolute url
			if webDocRec[2] and webDocRec[2][0] == '/':
				webDocArgs.append(self.customer_.getUrl() + webDocRec[2])
			else:
				webDocArgs.append(webDocRec[2])

			webDocArgs.append(webDocRec[2])

			if webDocRec[3]:
				entityFactory = EntityFactoryManager.findFactory(webDocRec[3])
				entity = entityFactory.createEntity(webDocRec[3])
				webDocArgs.append(entity)
			else:
				webDocArgs.append(NoneEntity())

			webDocArgs.append(webDocRec[4])

			if webDocRec[5]:
				entityFactory = EntityFactoryManager.findFactory("Date")
				entity = entityFactory.createEntity(webDocRec[5])
				webDocArgs.append(entity)
			else:
				webDocArgs.append(NoneEntity())

			if webDocRec[6]:
				entityFactory = EntityFactoryManager.findFactory(webDocRec[6])
				entity = entityFactory.createEntity(webDocRec[6])
				webDocArgs.append(entity)
			else:
				webDocArgs.append(NoneEntity())

			if webDocRec[7]:
				entityFactory = EntityFactoryManager.findFactory("PriceTag")
				entity = entityFactory.createEntity(webDocRec[7])
				webDocArgs.append(entity)
			else:
				webDocArgs.append(NoneEntity())
				
			webDocArgs.append(webDocRec[8])

			webDocArgs.append(webDocRec[9])

		except EntityFactoryManager.NoSuchEntityFactory, e:
			log.error("caught exception NoSuchEntityFactory, reason: %s" % e)
			raise
		except InvalidData.InvalidData, e:
			log.error("caught exception InvalidData, reason: %s" % e)
			raise

		return webDocArgs


	def getWebDocuments(self):
		return self.webDocs_


	def getCustomer(self):
		return self.customer_		


	def hasWebDocument(self, webDoc):
		return self.webDocs_.has_key(webDoc.getRelativeUrl())


	def addWebDocument(self, webDoc):
		if webDoc.getId() == -1:
			relUrl = webDoc.getRelativeUrl()
			if webDoc.isRoot() and self.webDocs_.has_key(relUrl) and self.webDocs_[relUrl].getId() == -1 or not self.webDocs_.has_key(relUrl):
				self.insertWebDocument(webDoc)
		else:
			self.updateWebDocument(webDoc)


	def insertWebDocument(self, webDoc):
		log = logger.getLogger()
		try:
			cursor = DBManager.getCursor()
			log.debug("Inserting webDocument = \"%s\" to database..." % webDoc.getName())
			webDoc.setCustomerId(self.customer_.getId())
			cursor.execute("INSERT INTO webdocument (customer_id, url, name, images, when_date, duration, price, last_crawl, content_length) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s)", webDoc.toInsertTuple(imageNumLimit = MAX_NUM_IMAGES, nameLenLimit = MAX_NAME_LEN))

			DBManager.commit()

			cursor.execute("SELECT MAX(id) FROM webdocument")
			id = cursor.fetchone()[0]
			webDoc.setId(id)

			cursor.close()

			log.debug("WebDocument has been inserted, id = %s." % id)


			self.webDocs_[webDoc.getRelativeUrl()] = webDoc 

		except MySQLdb.Error, e:
			log.error("MySQLdb error %d: %s" % (e.args[0], e.args[1]))
			raise


	def updateWebDocument(self, webDoc):
		log = logger.getLogger()
		try:
			cursor = DBManager.getCursor()
			log.debug("Updating webDocument = \"%s\" in database..." % webDoc.getName())
			cursor.execute("UPDATE webdocument SET customer_id = %s, url = %s, name = %s, images = %s, when_date = %s, duration = %s, price = %s, last_crawl = %s, content_length = %s WHERE id = %s", webDoc.toUpdateTuple(imageNumLimit = MAX_NUM_IMAGES, nameLenLimit = MAX_NAME_LEN))

			DBManager.commit()
			log.debug("Webdocument has been updated.")

			cursor.close()

		except MySQLdb.Error, e:
			log.error("MySQLdb error %d: %s" % (e.args[0], e.args[1]))
			raise


	def removeWebDocument(self, webDoc):
		log = logger.getLogger()
		try:
			cursor = DBManager.getCursor()
			log.debug("Deleting webDocument = \"%s\" from database..." % webDoc.getRelativeUrl())
			cursor.execute("DELETE FROM webdocument WHERE id = %s", webDoc.getId())

			DBManager.commit()
			log.debug("Webdocument has been deleted.")

			cursor.close()

		except MySQLdb.Error, e:
			log.error("MySQLdb error %d: %s" % (e.args[0], e.args[1]))
			raise
